#include "RPCheader.h"

int displayParms (int *argTypes, void **args);


int main(void) {

	int argTypes[PARAMETER_COUNT+1];
	void **args = (void **)malloc(PARAMETER_COUNT  * sizeof(void *));

	// void copyChar(dest, src);

	int result = 23;                         // Why 23?  Why not 23?
	/*char dest = 'd';
	char src  = 's';
	argTypes[0] = rpcChar | rpcOutput;       // dest
	argTypes[1] = rpcChar | rpcInput;        // src
	argTypes[2] = 0;                         // Terminator

	args[0] = (void *)&dest;
	args[1] = (void *)&src;*/

  	int* vector  = (int*)malloc(4*sizeof(int));
	  vector[0] = 12;
	  vector[1] = 13;
	  vector[2] = 1;
	  vector[3] = 99;
	  char x = 'h';
	  char *y = "fishies";
	  char *z[3] = {"fish","and","chips"};

	  argTypes[0] = rpcInt    |     rpcInput | rpcPartialMatch;   // Result
	  argTypes[1] = rpcInt    | 4 | rpcInput | rpcPartialMatch;   // Vector
	  argTypes[2] = rpcChar   |     rpcInput | rpcPartialMatch;   // x
	  argTypes[3] = rpcString |     rpcInput | rpcPartialMatch;   // y
	  argTypes[4] = rpcString | 3 | rpcInput | rpcPartialMatch;   // z
	  argTypes[5] = 0;                                            // Terminator

	  args[0] = (void *)&result;
	  args[1] = (void *) vector;
	  args[2] = (void *)&x;
	  args[3] = (void *) y;
	  args[4] = (void *) z;

	  std::cerr << "Y is " << y << std::endl
			<< "&Y is " << &y << std::endl
			<< "Z is " << z << std::endl
			<< "&Z is " << &z << std::endl
			<< z[0] << std::endl
			<< z[1] << std::endl
	<< z[2] << std::endl;

	cout << "Calling rpcPackData..." << endl;

	void *response = (void *)malloc(MAX_LENGTH * sizeof(void *));
	int responseLength = 0;

	rpcPackData(argTypes, args, response, &responseLength);

	cout << "LENGTH IS: " << responseLength << endl;

	cout << "Calling rpcExtractData... " << endl;

	thread_data param;

	//extract data from message and place in param struct
	rpcExtractData(response, &param, responseLength);

	displayParms(param.argTypes, param.args);

	free(reponse);

}

int displayParms (int *argTypes, void **args) {

  std::cerr << "You have entered the server displayParms" << std::endl;

  for (int i = 0; argTypes[i] != 0; ++i) {

    int arrayLength = argTypes[i] & 0xFFFF;

    switch ((argTypes[i] & 0xFF0000) >> 16) {
    case ARG_CHAR :
      std::cerr << "Argument " << i << " is char with value: " << *(char *)args[i] << std::endl;
      if (arrayLength) {
        std::cerr << "Argument is an array of length " << arrayLength << std::endl;
        std::cerr << "Last value of array is " << ((char *)args[i])[arrayLength - 1] << std::endl;
      }
      break;

    case ARG_SHORT :
      std::cerr << "Argument " << i << " is short with value: " << *(short *)args[i] << std::endl;
      if (arrayLength) {
        std::cerr << "Argument is an array of length " << arrayLength << std::endl;
        std::cerr << "Last value of array is " << ((short *)args[i])[arrayLength - 1] << std::endl;
      }
      break;

    case ARG_INT :
      std::cerr << "Argument " << i << " is int with value: " << *(int *)args[i] << std::endl;
      if (arrayLength) {
        std::cerr << "Argument is an array of length " << arrayLength << std::endl;
        std::cerr << "Last value of array is " << ((int *)args[i])[arrayLength - 1] << std::endl;
      }
      break;

    case ARG_LONG :
      std::cerr << "Argument " << i << " is long with value: " << *(long *)args[i] << std::endl;
      if (arrayLength) {
        std::cerr << "Argument is an array of length " << arrayLength << std::endl;
        std::cerr << "Last value of array is " << ((long *)args[i])[arrayLength - 1] << std::endl;
      }
      break;

    case ARG_FLOAT :
      std::cerr << "Argument " << i << " is float with value: " << *(float *)args[i] << std::endl;
      if (arrayLength) {
        std::cerr << "Argument is an array of length " << arrayLength << std::endl;
        std::cerr << "Last value of array is " << ((float *)args[i])[arrayLength - 1] << std::endl;
      }
      break;

    case ARG_DOUBLE :
      std::cerr << "Argument " << i << " is double with value: " << *(double *)args[i] << std::endl;
      if (arrayLength) {
        std::cerr << "Argument is an array of length " << arrayLength << std::endl;
        std::cerr << "Last value of array is " << ((double *)args[i])[arrayLength - 1] << std::endl;
      }
      break;

    case ARG_STRING :
	if (!arrayLength) {
	    std::cerr << "Argument " << i << " is string with value: " << (char *)args[i] << std::endl;
	}
	else {
	    std::cerr << "Argument is an array of length " << arrayLength << std::endl;
	    std::cerr << "First value of array is " << ((char**)args[i])[0] << std::endl;
	    std::cerr << "Last value of array is " << ((char**)args[i])[arrayLength - 1] << std::endl;
	}
      break;

    default :
      std::cerr << "Argument " << i << " is of unknown type" << std::endl;
      break;
    }

  }
  return 0;
}
